from collections import namedtuple
from inspect import getgeneratorstate


def client_consume():
    """
    >>> subg = client_consume()
    >>> subg
    """
    print("normal fun")
    results = {}
    for key in range(3):
        print("build exhaust for", key)
        group = grouper(results, key)
        for _ in group:
            print("_", _)
            if _ > 5:
                break
        print("    (id of group", group, ")")

    print("results", results)


def grouper(results, key):  # 委托生成器
    su = 0
    # for i in range(2):  # 可能会耗尽
    for i in range(3):
        sgen = get_three(i + key)
        print("gen delegate for", key, sgen)
        obj = yield from sgen  # 迭代式 yield from iterable. obj 永远是 坑 !空!
        # sgen为 生成器的时候, obj为list, 普通函数时, 生成器串行产出(!!而不是obj接受!!) list元素
        # obj = yield from sgen  # 推送式 迭代器返回非None值
        print("return normal iterable", obj)
        su += obj or 0
    print("su", su)
    results[key] = su / 3


Result = namedtuple("Result", ["count", "avg"])


def get_three(i):
    # raise StopIteration(i) # 不能抛出 SI异常 RuntimeError: generator raised StopIteration
    # next(iter(()))  # 不能抛出 SI异常 RuntimeError: generator raised StopIteration
    return [1 + i, 2 + i, 3 + i]  # 引导 返值 StopIteration 异常
    # yield i  # todo yield
    # 若是普通函数,返回必须为iterable 坑 只是为了把def 改成 gen!


client_consume()
if __name__ == "__main__" and False:
    import doctest

    print("yieldfrom 测试开始")
    (ff, tt) = doctest.testmod()
    print("测试结束:统计-失败{},总计{}".format(ff, tt))
    print("√" * tt if tt > 0 and not ff else "无测试" if not ff else "×" * ff)
